/***
 *  C++ 多态
 *      一、静态多态（编译期确定）
 *          1、函数重载
 *          2、运算符重载
 *          3、模板编程: 模板函数，模板类
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <vector>

// 自定义类 Point
class Points {
public:
    // 构造函数
    Points(int x = 0, int y = 0) : m_x(x), m_y(y) {}

private:
    int m_x;
    int m_y;
};

// arithmetic unit
// 运算单元
class AritchmeticUnit{
    double m_dPartOne{0.0};
    double m_dPartTwo{0.0};
public:
    AritchmeticUnit(){}
    AritchmeticUnit(double real1, double real2):m_dPartOne(real1), m_dPartTwo(real2){}
    
    // 函数重载
    int add(int a, int b) 
    {
         return a + b;
    }

    double add(double a, double b) 
    { 
        m_dPartOne = a;
        m_dPartTwo = b;
        return a + b; 
    }
    
    // 运算符重载
    AritchmeticUnit operator+(const AritchmeticUnit& a1){
        AritchmeticUnit retA(m_dPartOne + a1.m_dPartOne, m_dPartTwo + a1.m_dPartTwo);
        return retA;
   }

   // 重载 << 运算符用于输出
   friend std::ostream& operator<<(std::ostream& out, const AritchmeticUnit& c) {
        out <<"value: " << c.m_dPartOne << ", " << c.m_dPartTwo;
        return out;
    }   

    // 函数模板
    template<typename T, typename M>
    T subtr(T& a, M& b)
    {
        
        T ret = 0;
        // 打印数的实际类型
        const char* chT = typeid(T).name();
        const char* chM = typeid(M).name();
        std::cout << "T type: " << chT << std::endl;
        std::cout << "M type: " << chM << std::endl;
        if( (0 == std::strcmp("i", chT)) && (0 == std::strcmp("d",chM)) )
        {
            ret = 1;
        }
        return ret;
    }
};

// 定义一个类模板
template <typename T>
class Stack {
public:
    // 入栈操作
    void push(T element) {
        m_elements.push_back(element);
    }

    // 出栈操作
    T pop() {
        if (m_elements.empty()) {
            throw std::out_of_range("Stack is empty");
        }
        T top = m_elements.back();
        m_elements.pop_back();
        return top;
    }

    // 判断栈是否为空
    bool isEmpty() const {
        return m_elements.empty();
    }
private:
    std::vector<T> m_elements;
};

int main()
{
    AritchmeticUnit aritUnit;
    int iRet = aritUnit.add(3, 5);
    double dRet = aritUnit.add(4.12, 3.85);
    printf("iRet = %d, dRet=%f\n", iRet, dRet);

    AritchmeticUnit aritUnit1(3.88, 6.66);

    AritchmeticUnit aritUnit2 = aritUnit1+aritUnit;

    std::cout <<"aritUnit2: " << aritUnit2 <<std::endl;

    // 模板函数
    int iA = 13;
    double dA = 19.6;
    AritchmeticUnit aritRet;
    int iR = aritRet.subtr(iA, dA);
    std::cout << "iR: " << iR <<std::endl;
    int iR1 = aritRet.subtr(dA, iA);
    std::cout << "iR1: " << iR1 <<std::endl;
    Points p(10, 15);
    int iR2 = aritRet.subtr<int, Points>(iA, p);
    std::cout << "iR2: " << iR2 <<std::endl;

    // 模板类
    // 创建一个存储整数的栈
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    std::cout << "Popped from intStack: " << intStack.pop() << std::endl;
    std::cout << "Popped from intStack: " << intStack.pop() << std::endl;

    // 创建一个存储字符串的栈
    Stack<std::string> stringStack;
    stringStack.push("Hello");
    stringStack.push("World");
    std::cout << "Popped from stringStack: " << stringStack.pop() << std::endl;
    std::cout << "Popped from stringStack: " << stringStack.pop() << std::endl;
    
    return 0;
}